// vim:ft=javascript

function mongodb_generate_header(inpath, outpath, replacements)
{
  STDOUT.WriteLine("Generating " + outpath);

  var infile = FSO.OpenTextFile(inpath, 1);
  var outdata = infile.ReadAll();
  infile.Close();

  for (var key in replacements) {
    var replacement = replacements[key];

    if (typeof replacement === 'string') {
      replacement = replacement.replace(/"/g, '\\"');
    }

    outdata = outdata.replace(new RegExp('@' + key + '@', 'g'), replacement);
  }

  var outfile = FSO.CreateTextFile(outpath, true);
  outfile.Write(outdata);
  outfile.Close();
}

function mongodb_parse_version_file(inpath, prefix)
{
  var infile = FSO.OpenTextFile(inpath, 1);
  var version = infile.ReadLine();
  infile.Close();

  var xyz_pre = version.split("-");
  var xyz = xyz_pre[0].split(".");
  var pre = xyz_pre.length > 1 ? xyz_pre[1] : "";

  var replacements = {};
  replacements[prefix + "VERSION"] = version;
  replacements[prefix + "MAJOR_VERSION"] = xyz[0];
  replacements[prefix + "MINOR_VERSION"] = xyz[1];
  replacements[prefix + "MICRO_VERSION"] = xyz[2];
  replacements[prefix + "PRERELEASE_VERSION"] = pre;

  return replacements;
}

ARG_ENABLE("mongodb", "MongoDB support", "no");
ARG_WITH("mongodb-sasl", "MongoDB: Build against Cyrus-SASL", "yes");

if (PHP_MONGODB != "no") {
  /* Note: ADD_EXTENSION_DEP() cannot be used to declare that we depend on the
   * date and standard extensions. Assume that they're always enabled. */
  ADD_EXTENSION_DEP("mongodb", "json", false);
  ADD_EXTENSION_DEP("mongodb", "spl", false);

  /* MongoDB does not actually depend on PHP's OpenSSL extension, but this is in
   * place to ensure that later SSL library checks succeed. This can be removed
   * once we support building with Secure Channel. */
  ADD_EXTENSION_DEP("mongodb", "openssl", false);

  ADD_FLAG("CFLAGS_MONGODB", " /D BSON_COMPILATION /D MONGOC_COMPILATION /D MONGOC_TRACE /I" + configure_module_dirname + " /I" + configure_module_dirname + "/src/libmongoc/src/mongoc" + " /I" + configure_module_dirname + "/src/libbson/src/bson/ /I" + configure_module_dirname + "/src/libbson/src /I" + configure_module_dirname + "/src/contrib");
  EXTENSION("mongodb", "php_phongo.c");
  ADD_SOURCES(configure_module_dirname + "/", "phongo_compat.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src", "bson.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/BSON", "Type.c Unserializable.c Serializable.c Persistable.c Binary.c Decimal128.c Javascript.c MaxKey.c MinKey.c ObjectID.c Regex.c Timestamp.c UTCDateTime.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "Command.c Cursor.c CursorId.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c BulkWrite.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Exception", "Exception.c LogicException.c RuntimeException.c UnexpectedValueException.c InvalidArgumentException.c ConnectionException.c AuthenticationException.c SSLConnectionException.c ExecutionTimeoutException.c ConnectionTimeoutException.c WriteException.c BulkWriteException.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libbson/src/yajl", "yajl_version.c yajl.c yajl_encode.c yajl_lex.c yajl_parser.c yajl_buf.c yajl_tree.c yajl_alloc.c yajl_gen.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libbson/src/bson", "bcon.c bson.c bson-atomic.c bson-clock.c bson-context.c bson-decimal128.c bson-error.c bson-iter.c bson-iso8601.c bson-json.c bson-keys.c bson-md5.c bson-memory.c bson-oid.c bson-reader.c bson-string.c bson-timegm.c bson-utf8.c bson-value.c bson-version-functions.c bson-writer.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-apm.c mongoc-array.c mongoc-async.c mongoc-async-cmd.c mongoc-buffer.c mongoc-bulk-operation.c mongoc-b64.c mongoc-client.c mongoc-client-pool.c mongoc-cluster.c mongoc-collection.c mongoc-counters.c mongoc-cursor.c mongoc-cursor-array.c mongoc-cursor-cursorid.c mongoc-cursor-transform.c mongoc-database.c mongoc-find-and-modify.c mongoc-host-list.c mongoc-init.c mongoc-gridfs.c mongoc-gridfs-file.c mongoc-gridfs-file-page.c mongoc-gridfs-file-list.c mongoc-handshake.c mongoc-index.c mongoc-linux-distro-scanner.c mongoc-list.c mongoc-log.c mongoc-matcher-op.c mongoc-matcher.c mongoc-memcmp.c mongoc-opcode.c mongoc-queue.c mongoc-read-concern.c mongoc-read-prefs.c mongoc-rpc.c mongoc-server-description.c mongoc-server-stream.c mongoc-set.c mongoc-socket.c mongoc-stream.c mongoc-stream-buffered.c mongoc-stream-file.c mongoc-stream-gridfs.c mongoc-stream-socket.c mongoc-topology.c mongoc-topology-description.c mongoc-topology-description-apm.c mongoc-topology-scanner.c mongoc-uri.c mongoc-util.c mongoc-version-functions.c mongoc-write-command.c mongoc-write-concern.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-crypto.c mongoc-scram.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-stream-tls.c mongoc-ssl.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-crypto-openssl.c mongoc-rand-openssl.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-openssl.c mongoc-stream-tls-openssl.c mongoc-stream-tls-openssl-bio.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-crypto-common-crypto.c mongoc-rand-common-crypto.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-secure-transport.c mongoc-stream-tls-secure-transport.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-crypto-cng.c mongoc-rand-cng.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-secure-channel.c mongoc-stream-tls-secure-channel.c", "mongodb");
  ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/mongoc", "mongoc-sasl.c", "mongodb");

  var bson_opts = {
    BSON_BYTE_ORDER: 1234,
    BSON_OS: 2,
    BSON_HAVE_STDBOOL_H: 0,
    BSON_HAVE_ATOMIC_32_ADD_AND_FETCH: 0,
    BSON_HAVE_ATOMIC_64_ADD_AND_FETCH: 0,
    BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES: 0,
    BSON_HAVE_CLOCK_GETTIME: 0,
    BSON_HAVE_STRNLEN: 0,
    BSON_HAVE_SNPRINTF: 0,
    BSON_HAVE_REALLOCF: 0,
    BSON_NEEDS_SET_OUTPUT_FORMAT: 0,
    BSON_HAVE_TIMESPEC: 0,
    BSON_EXTRA_ALIGN: 0,
    BSON_HAVE_SYSCALL_TID: 0,
    BSON_HAVE_DECIMAL128: 0
  };

  if (CHECK_FUNC_IN_HEADER("stdio.h", "_set_output_format")) {
    bson_opts.BSON_NEEDS_SET_OUTPUT_FORMAT = 1;
  }

  mongodb_generate_header(
    configure_module_dirname + "/src/libbson/src/bson/bson-config.h.in",
    configure_module_dirname + "/src/libbson/src/bson/bson-config.h",
    bson_opts
  );

  mongodb_generate_header(
    configure_module_dirname + "/src/libbson/src/bson/bson-version.h.in",
    configure_module_dirname + "/src/libbson/src/bson/bson-version.h",
    mongodb_parse_version_file(configure_module_dirname + "/src/libbson/VERSION_CURRENT", "BSON_")
  );

  var mongoc_opts = {
    // TODO: Support building with Secure Channel on Windows
    MONGOC_ENABLE_SSL_SECURE_CHANNEL: 0,
    MONGOC_ENABLE_CRYPTO_CNG: 0,
    // Secure Transport does not apply to Windows
    MONGOC_ENABLE_SSL_SECURE_TRANSPORT: 0,
    MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO: 0,
    MONGOC_ENABLE_SSL_LIBRESSL: 0,
    MONGOC_ENABLE_SSL_OPENSSL: 0,
    MONGOC_ENABLE_CRYPTO_LIBCRYPTO: 0,
    MONGOC_ENABLE_SSL: 0,
    MONGOC_ENABLE_CRYPTO: 0,
    MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE: 0,
    MONGOC_ENABLE_SASL: 0,
    MONGOC_HAVE_SASL_CLIENT_DONE: 0,
    MONGOC_HAVE_WEAK_SYMBOLS: 0,
    MONGOC_NO_AUTOMATIC_GLOBALS: 1,
    MONGOC_CC: "",
    MONGOC_USER_SET_CFLAGS: "",
    MONGOC_USER_SET_LDFLAGS: ""
  };

  var mongoc_ssl_path_to_check = PHP_MONGODB;

  if (typeof PHP_OPENSSL === 'string') {
    mongoc_ssl_path_to_check += ";" + PHP_OPENSSL;
  }

  if (CHECK_LIB("ssleay32.lib", "mongodb", mongoc_ssl_path_to_check) &&
      CHECK_LIB("libeay32.lib", "mongodb", mongoc_ssl_path_to_check) &&
      CHECK_LIB("crypt32.lib", "mongodb") &&
      CHECK_HEADER_ADD_INCLUDE("openssl/ssl.h", "CFLAGS_MONGODB")) {
    mongoc_opts.MONGOC_ENABLE_SSL_OPENSSL = 1;
    mongoc_opts.MONGOC_ENABLE_CRYPTO_LIBCRYPTO = 1;
    mongoc_opts.MONGOC_ENABLE_SSL = 1;
    mongoc_opts.MONGOC_ENABLE_CRYPTO = 1;
  } else {
    WARNING("mongodb libopenssl support not enabled, libs not found");
  }

  if (PHP_MONGODB_SASL != "no" &&
      CHECK_LIB("libsasl.lib", "mongodb", PHP_MONGODB) &&
      CHECK_HEADER_ADD_INCLUDE("sasl/sasl.h", "CFLAGS_MONGODB")) {
    mongoc_opts.MONGOC_ENABLE_SASL = 1;
    if (CHECK_FUNC_IN_HEADER("sasl/sasl.h", "sasl_client_done")) {
      mongoc_opts.MONGOC_HAVE_SASL_CLIENT_DONE = 1;
    }
  } else {
    WARNING("mongodb libsasl support not enabled, libs not found");
  }

  if (typeof COMPILER_NAME === 'string') {
    mongoc_opts.MONGOC_CC = COMPILER_NAME;
  } else if (typeof VC_VERSIONS[VCVERS] === 'string') {
    mongoc_opts.MONGOC_CC = VC_VERSIONS[VCVERS];
  }

  /* MONGOC_USER_SET_CFLAGS and MONGOC_USER_SET_LDFLAGS can be left blank, as we
   * do not expect CFLAGS or LDFLAGS to be customized at build time. */

  mongodb_generate_header(
    configure_module_dirname + "/src/libmongoc/src/mongoc/mongoc-config.h.in",
    configure_module_dirname + "/src/libmongoc/src/mongoc/mongoc-config.h",
    mongoc_opts
  );

  mongodb_generate_header(
    configure_module_dirname + "/src/libmongoc/src/mongoc/mongoc-version.h.in",
    configure_module_dirname + "/src/libmongoc/src/mongoc/mongoc-version.h",
    mongodb_parse_version_file(configure_module_dirname + "/src/libmongoc/VERSION_CURRENT", "MONGOC_")
  );
}

